package ru.susu.algebra.chartable.degree;

import java.math.BigInteger;
import java.util.HashMap;

import ru.susu.algebra.partition.Partition;
import ru.susu.algebra.partition.operation.ChangePartitionElementOperation;

/**
 * @author akargapolov
 * @since: 06.09.2009
 */
public class KnutDegreeCalculator implements IDegreeCalculator
{
	private HashMap<Partition, BigInteger> _degrees = new HashMap<Partition, BigInteger>();
	private static Integer ZERO = Integer.valueOf(0);

	@Override
	public BigInteger calculateDegree(Partition p)
	{
		if (_degrees.containsKey(p))
			return _degrees.get(p);

		if (ZERO.equals(p.getPresentedNumber()))
			return BigInteger.ONE;

		Integer[] array = p.getArrayRepresentation();
		Partition lastP = null;
		ChangePartitionElementOperation op = new ChangePartitionElementOperation();

		BigInteger result = BigInteger.ZERO;
		for (int index = 0; index < array.length; index++)
		{
			Partition newP = op.performOperation(p, index, -1);
			if (newP.equals(lastP))
				continue;
			result = result.add(this.calculateDegree(newP));
			lastP = newP;
		}
		_degrees.put(p, result);
		return result;
	}
}
